package com.example.translateappjava.Service.YOLOAPI;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Log;
// 引入 LoadingProgressListener
import com.example.translateappjava.Listener.LoadingProgressListener;

import org.json.JSONArray;
import org.json.JSONObject;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody; // 确保引入 ResponseBody

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Locale; // 用于 SimpleDateFormat
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ImageUploader {
    private final String IP = "http://47.120.15.23:6003/";
    private ExecutorService executorService = Executors.newSingleThreadExecutor();
    private LoadingProgressListener loadingProgressListener; // <<< 新增

    private ArrayList<String> URLs;
    private OkHttpClient client = new OkHttpClient();

    private ArrayList<Bitmap> bitmaps;
    private ArrayList<byte[]> bytes;
    private int length = -1; // 总图片数
    private int downloadedCount = 0; // 已下载图片计数

    private ImageUploadCallback callback;

    // 新增：设置进度监听器的方法
    public void setLoadingProgressListener(LoadingProgressListener listener) {
        this.loadingProgressListener = listener;
    }

    public void uploadImage(Bitmap bitmap, ImageUploadCallback callback) {
        this.callback = callback;
        this.downloadedCount = 0; // 重置下载计数
        this.length = -1;         // 重置总图片数

        if (loadingProgressListener != null) {
            loadingProgressListener.onProgressUpdate("准备上传图片...", "");
        }

        executorService.submit(() -> {
            String timestamp = new SimpleDateFormat("yyyyMMdd_HHmmss_SSS", Locale.getDefault()).format(new Date());
            String fileName = "upload_image_" + timestamp + ".jpg";
            String uploadUrl = IP + "upload?image=" + fileName;

            HttpURLConnection connection = null;
            try {
                Log.d("ImageUploaderInternal", "Attempting to call onProgressUpdate. Listener is: " + (loadingProgressListener == null ? "NULL" : "VALID"));
                if (loadingProgressListener != null) {
                    loadingProgressListener.onProgressUpdate("正在上传图片到服务器...", fileName);
                }
                URL url = new URL(uploadUrl);
                connection = (HttpURLConnection) url.openConnection();
                connection.setDoOutput(true);
                connection.setRequestMethod("POST");
                connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=*****");
                // 初始化列表，以防多次调用uploadImage导致数据累积
                bitmaps = new ArrayList<>();
                bytes = new ArrayList<>();
                URLs = new ArrayList<>();


                ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
                bitmap.compress(Bitmap.CompressFormat.JPEG, 40, byteArrayOutputStream);
                byte[] bitmapData = byteArrayOutputStream.toByteArray();

                DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream());
                outputStream.writeBytes("--*****\r\n");
                outputStream.writeBytes("Content-Disposition: form-data; name=\"image\"; filename=\"" + fileName + "\"\r\n");
                outputStream.writeBytes("Content-Type: image/jpeg\r\n");
                outputStream.writeBytes("\r\n");

                outputStream.write(bitmapData);
                outputStream.writeBytes("\r\n");
                outputStream.writeBytes("--*****--\r\n");
                outputStream.flush();
                outputStream.close(); // 关闭流

                int responseCode = connection.getResponseCode();
                if (responseCode == HttpURLConnection.HTTP_OK) {
                    Log.d("ImageUploaderInternal", "Attempting to call onProgressUpdate. Listener is: " + (loadingProgressListener == null ? "NULL" : "VALID"));
                    if (loadingProgressListener != null) {
                        loadingProgressListener.onProgressUpdate("图片上传成功", "等待服务器处理...");
                    }
                    InputStream responseStream = connection.getInputStream();
                    BufferedReader reader = new BufferedReader(new InputStreamReader(responseStream));
                    StringBuilder response = new StringBuilder();
                    String line;
                    while ((line = reader.readLine()) != null) {
                        response.append(line);
                    }
                    reader.close();
                    responseStream.close(); // 关闭流
                    handleServerResponse(response.toString());
                } else {
                    if (loadingProgressListener != null) {
                        loadingProgressListener.onProgressUpdate("图片上传失败", "服务器响应: " + responseCode);
                    }
                    handleErrorResponse(connection.getErrorStream(), bitmap, 0); // 初始重试次数为0
                }
            } catch (IOException e) {
                Log.e("Upload", "Upload IO Exception: " + e.getMessage(), e);
                if (loadingProgressListener != null) {
                    loadingProgressListener.onProgressUpdate("图片上传异常", e.getMessage());
                }
                // 这里也应该考虑重试或直接回调失败
                // 为了简化，我们先假设IO异常直接失败或进行一次重试
                if (connection != null) {
                    handleErrorResponse(connection.getErrorStream(), bitmap, 0);
                } else if (callback != null) {
                    callback.onUploadFailed(e);
                }
            } finally {
                if (connection != null) {
                    connection.disconnect();
                }
            }
        });
    }

    private void handleErrorResponse(InputStream errorStream, Bitmap bitmap, int currentRetryCount) {
        final int MAX_RETRY_COUNT = 3; // 减少重试次数，避免长时间等待

        if (currentRetryCount < MAX_RETRY_COUNT) {
            int nextRetry = currentRetryCount + 1;
            Log.d("Upload", "上传失败，尝试重传... 第 " + nextRetry + " 次");
            if (loadingProgressListener != null) {
                loadingProgressListener.onProgressUpdate("上传失败，正在重试...", "第 " + nextRetry + "/" + MAX_RETRY_COUNT + " 次尝试");
            }
            // 简单的延迟后重试
            try {
                Thread.sleep(1000 * nextRetry); // 延迟时间随重试次数增加
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
            uploadImage(bitmap, callback); // 重新调用上传方法，注意这会重置内部状态
        } else {
            Log.e("Upload", "图片上传在 " + MAX_RETRY_COUNT + " 次尝试后失败。");
            if (loadingProgressListener != null) {
                loadingProgressListener.onProgressUpdate("图片上传失败", "已达最大重试次数");
            }
            if (callback != null) {
                // 尝试从errorStream读取错误信息
                String errorMsg = "Upload failed after " + MAX_RETRY_COUNT + " attempts";
                if (errorStream != null) {
                    try (BufferedReader reader = new BufferedReader(new InputStreamReader(errorStream))) {
                        StringBuilder sb = new StringBuilder();
                        String line;
                        while ((line = reader.readLine()) != null) {
                            sb.append(line);
                        }
                        if (sb.length() > 0) errorMsg += ". Server error: " + sb.toString();
                    } catch (IOException ex) {
                        Log.e("Upload", "Error reading error stream: " + ex.getMessage());
                    }
                }
                callback.onUploadFailed(new IOException(errorMsg));
            }
        }
    }


    public void handleServerResponse(String serverResponse) {
        Log.d("Upload", "正在处理服务器响应...");
        if (loadingProgressListener != null) {
            loadingProgressListener.onProgressUpdate("服务器响应已接收", "正在解析数据...");
        }
        try {
            JSONObject responseJson = new JSONObject(serverResponse);
            if (responseJson.has("generated_images")) {
                JSONArray generatedImages = responseJson.getJSONArray("generated_images");
                length = generatedImages.length(); // <<< 获取总图片数
                Log.d("Upload", "服务器生成了 " + length + " 张图片。"); // <<< 你的Log.d

                if (loadingProgressListener != null) {
                    loadingProgressListener.onProgressUpdate("解析完成，准备下载图片", "共 " + length + " 张");
                }

                if (length == 0) {
                    Log.w("Upload", "服务器未生成任何图片。");
                    if (loadingProgressListener != null) {
                        loadingProgressListener.onProgressUpdate("处理完成", "服务器未返回图片");
                    }
                    if (callback != null) { // 如果没有图片，也应该通知完成
                        // 确保列表是空的
                        callback.onUploadComplete(new ArrayList<>(), new ArrayList<>(), new ArrayList<>());
                    }
                    return;
                }


                for (int i = 0; i < generatedImages.length(); i++) {
                    String imagePath = generatedImages.getString(i).replace("output_images", "").replace("\\", "").replace("%5C","");
                    String imageUrl = IP + "download/" + imagePath;
                    System.out.println("准备下载图片URL: " + imageUrl); // <<< 你的System.out.println
                    downloadImage(imageUrl, 0, i + 1); // 传递当前图片序号
                }
            } else {
                Log.e("Upload", "服务器响应中未找到 'generated_images'。");
                if (loadingProgressListener != null) {
                    loadingProgressListener.onProgressUpdate("响应格式错误", "未找到图片列表");
                }
                if (callback != null) {
                    callback.onUploadFailed(new Exception("Server response missing 'generated_images'"));
                }
            }
        } catch (Exception e) {
            Log.e("Upload", "处理服务器响应时出错: " + e.getMessage(), e);
            if (loadingProgressListener != null) {
                loadingProgressListener.onProgressUpdate("响应处理异常", e.getMessage());
            }
            if (callback != null) {
                callback.onUploadFailed(e);
            }
        }
    }

    public void downloadImage(String imageUrl, int currentRetryCount, final int imageNumber) { // 添加 imageNumber
        final int MAX_RETRIES = 3;

        if (loadingProgressListener != null && currentRetryCount == 0) { // 仅在首次尝试时更新
            loadingProgressListener.onProgressUpdate("开始下载第 " + imageNumber + " 张图片...", "共 " + length + " 张");
        }

        Request request = new Request.Builder()
                .url(imageUrl)
                .build();

        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                handleDownloadRetryOrFailure(e, imageUrl, currentRetryCount, imageNumber);
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                // try-with-resources 确保 ResponseBody 被关闭
                try (ResponseBody responseBody = response.body()) {
                    if (response.isSuccessful() && responseBody != null) {
                        InputStream inputStream = responseBody.byteStream();
                        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();

                        byte[] buffer = new byte[8096];
                        int bytesRead;
                        while ((bytesRead = inputStream.read(buffer)) != -1) {
                            byteArrayOutputStream.write(buffer, 0, bytesRead);
                        }
                        inputStream.close(); // 关闭流

                        byte[] imageData = byteArrayOutputStream.toByteArray();
                        Bitmap bitmap = BitmapFactory.decodeByteArray(imageData, 0, imageData.length);

                        if (bitmap != null) {
                            Log.d("Download", "图片 " + imageNumber + " 下载并解码成功。");
                            synchronized (ImageUploader.this) { // 同步块保护共享资源
                                bitmaps.add(bitmap);
                                bytes.add(imageData);
                                URLs.add(imageUrl);
                                downloadedCount++;
                            }

                            if (loadingProgressListener != null) {
                                loadingProgressListener.onProgressUpdate(
                                        "第 " + imageNumber + " 张图片下载完成 ("+ downloadedCount + "/" + length +")",
                                        ""
                                );
                            }

                            // 所有图片都已下载时，调用回调
                            if (downloadedCount == length && callback != null) {
                                if (loadingProgressListener != null) {
                                    loadingProgressListener.onProgressUpdate("所有图片下载完成!", "");
                                }
                                callback.onUploadComplete(bitmaps, bytes, URLs);
                            }
                        } else {
                            Log.e("Download", "图片 " + imageNumber + " 解码失败。URL: " + imageUrl);
                            handleDownloadRetryOrFailure(new IOException("图片 " + imageNumber + " 解码失败"), imageUrl, currentRetryCount, imageNumber);
                        }
                        byteArrayOutputStream.close(); // 关闭流
                    } else {
                        String errorDetail = "服务器响应不成功. Code: " + response.code();
                        if (responseBody != null) {
                            errorDetail += " Body: " + responseBody.string(); // 读取错误体，小心大文件
                        }
                        Log.e("Download", "下载图片 " + imageNumber + " 失败: " + errorDetail + " URL: " + imageUrl);
                        handleDownloadRetryOrFailure(new IOException("下载图片 " + imageNumber + " 失败: " + errorDetail), imageUrl, currentRetryCount, imageNumber);
                    }
                } catch (Exception e) { // 捕获更广泛的异常，例如 responseBody.string() 可能抛出的
                    Log.e("Download", "处理图片 " + imageNumber + " 响应时异常: " + e.getMessage(), e);
                    handleDownloadRetryOrFailure(new IOException("处理图片 " + imageNumber + " 响应时异常: " + e.getMessage(), e), imageUrl, currentRetryCount, imageNumber);
                }
            }

            private void handleDownloadRetryOrFailure(IOException e, String imageUrl, int retriesDone, int imgNum) {
                if (retriesDone < MAX_RETRIES) {
                    int nextRetry = retriesDone + 1;
                    Log.w("Download", "图片 " + imgNum + " 下载失败，尝试重试第 " + nextRetry + " 次。原因: " + e.getMessage());
                    if (loadingProgressListener != null) {
                        loadingProgressListener.onProgressUpdate(
                                "图片 " + imgNum + " 下载失败，重试中...",
                                "第 " + nextRetry + "/" + MAX_RETRIES + " 次尝试"
                        );
                    }
                    try {
                        Thread.sleep(1000 * nextRetry); // 简单的指数退避
                    } catch (InterruptedException interruptedException) {
                        Thread.currentThread().interrupt();
                        Log.e("Download", "下载重试等待时被打断");
                    }
                    downloadImage(imageUrl, nextRetry, imgNum);
                } else {
                    Log.e("Download", "图片 " + imgNum + " 在 " + MAX_RETRIES + " 次重试后下载失败。URL: " + imageUrl, e);
                    // 即使一张图片下载失败，也应该继续处理，或者标记它失败并通知上层
                    // 一个简化的处理是，如果一个失败了，整个过程就失败
                    if (loadingProgressListener != null) {
                        loadingProgressListener.onProgressUpdate("图片 " + imgNum + " 下载失败", "已达最大重试次数");
                    }
                    if (callback != null) {
                        // 为了避免多次调用 onUploadFailed，可以考虑设置一个标志位
                        // 或者，更复杂的逻辑是收集所有成功和失败的结果统一回调
                        // 此处简化为一旦有下载失败，则整体失败
                        synchronized (ImageUploader.this) {
                            if (downloadedCount != length) { // 确保不是所有都成功后又误报失败
                                synchronized (ImageUploader.this) {
                                    downloadedCount++; // 即使失败，也算作一个已处理的图片
                                    Log.e("Download", "图片 " + imgNum + " 最终下载失败。当前处理总数: " + downloadedCount + "/" + length);
                                    if (downloadedCount == length && callback != null) {
                                        // 如果所有图片都处理完毕（有些可能成功，有些可能失败）
                                        // 如果有任何失败，则整体算作失败
                                        // 这种策略意味着，只要有一个图片下载失败，即使其他的成功了，整个操作也算失败
                                        // 如果需要更细致的控制（例如返回部分成功的结果），这里的逻辑会更复杂
                                        Log.e("Download", "由于图片 " + imgNum + " 下载失败，整个批次标记为失败。");
                                        callback.onUploadFailed(new IOException("一张或多张图片下载失败，最后失败的是：" + imgNum, e));
                                    } else if (downloadedCount < length) {
                                        Log.d("Download", "图片 " + imgNum + " 下载失败，但仍有其他图片待处理。");
                                    }
                                }
                            }
                        }
                    }
                }
            }
        });
    }

    public interface ImageUploadCallback {
        void onUploadComplete(ArrayList<Bitmap> bitmaps, ArrayList<byte[]> bytes, ArrayList<String> URLs);
        void onUploadFailed(Exception e);
    }

    // Getters
    public ArrayList<String> getURLs() {
        return new ArrayList<>(URLs); // 返回副本以防外部修改
    }

    public ArrayList<Bitmap> getBitmaps() {
        return new ArrayList<>(bitmaps); // 返回副本
    }

    public ArrayList<byte[]> getBytes() {
        return new ArrayList<>(bytes); // 返回副本
    }
}